package com.devops.admin.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.devops.admin.mapper.DOSProjectGroupUserRelationMapper;
import com.devops.admin.model.DOSProjectGroupUserRelation;
import com.devops.admin.po.DOSProjectGroupUserRelationPo;
import com.devops.admin.po.DOSProjectGroupUserRolePo;
import com.devops.admin.po.DOSRolePo;
import com.devops.admin.service.DOSProjectGroupUserRelationService;
import com.devops.admin.service.DOSRoleUserRelationService;
import com.devops.admin.util.Assert;
import com.devops.admin.vo.DOSProjectGroupUserRelationVo;
import com.devops.constant.DOSRoleEnum;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @ClassName DOSProjectGroupUserRelationServiceImpl
 * @Description TODO
 * @Author heyabo
 * @Date 2022/9/5 15:51
 * @Version 1.0
 **/
@Service
public class DOSProjectGroupUserRelationServiceImpl extends ServiceImpl<DOSProjectGroupUserRelationMapper, DOSProjectGroupUserRelation> implements DOSProjectGroupUserRelationService {

    private final String MANAGER_ROLE_CODE = DOSRoleEnum.TECHNOLOGY_MANAGER.getRoleCode() + "," +
            DOSRoleEnum.ADMINISTRATOR.getRoleCode() + "," +
            DOSRoleEnum.QA_ADMINISTRATOR.getRoleCode() + "," +
            DOSRoleEnum.SUPER_ADMINISTRATOR.getRoleCode() + "," +
            DOSRoleEnum.WEB_MANAGER.getRoleCode();

    private final String USER_ROLE_CODE = DOSRoleEnum.TECHNOLOGY_MANAGER.getRoleCode() + "," +
            DOSRoleEnum.JAVA_ENGINEER.getRoleCode() + "," +
            DOSRoleEnum.WEB_ENGINEER.getRoleCode();

    @Autowired
    private DOSRoleUserRelationService dosRoleUserRelationService;

    @Override
    public Boolean saveProjectGroupUserRelation(DOSProjectGroupUserRelationVo relation) {
        Assert.isTrue(relation.getProjectGroupId() != null && relation.getProjectGroupId() > 0,"项目组id不能为空");
        Assert.isTrue(StrUtil.isNotBlank(relation.getUserType()),"人员类型不能为空");
        Assert.isTrue(relation.getUserType().equals("1") || relation.getUserType().equals("2"),"人员类型不合法");
        // 校验项目组分配的管理人员身份是否合法
        checkProjectGroupManager(relation);

        // 查询项目组已经绑定的人员
        LambdaQueryWrapper<DOSProjectGroupUserRelation> queryWrapper = Wrappers.<DOSProjectGroupUserRelation>lambdaQuery()
                .eq(DOSProjectGroupUserRelation::getProjectGroupId,relation.getProjectGroupId())
                .eq(DOSProjectGroupUserRelation::getUserType,relation.getUserType());

        //需要全部删除
        if (relation.getUserIds() == null || relation.getUserIds().size() == 0) {
            this.remove(queryWrapper);
        } else { //处理逻辑
            List<DOSProjectGroupUserRelation> saveRelations = new ArrayList<>();
            List<DOSProjectGroupUserRelation> projectGroupUserRelations = this.list(queryWrapper);
            List<String> userIds = projectGroupUserRelations.stream().map(DOSProjectGroupUserRelation::getUserId).collect(Collectors.toList());
            // 获取差集 - 需要保存的数据
            List<String> saveUserIds = relation.getUserIds().stream().filter(userId -> !userIds.contains(userId)).collect(Collectors.toList());
            // 获取差集 - 需要删除的数据
            List<String> deleteUserIds = userIds.stream().filter(userId -> !relation.getUserIds().contains(userId)).collect(Collectors.toList());
            // 组装需要保存的关系
            if (CollectionUtil.isNotEmpty(saveUserIds)){
                for (String userId : saveUserIds) {
                    DOSProjectGroupUserRelation userRelation = DOSProjectGroupUserRelation.builder()
                            .userId(userId)
                            .projectGroupId(relation.getProjectGroupId())
                            .userType(relation.getUserType())
                            .build();
                    saveRelations.add(userRelation);
                }
                this.saveBatch(saveRelations);
            }
            // 删除关系
            if (CollectionUtil.isNotEmpty(deleteUserIds)){
                queryWrapper.in(DOSProjectGroupUserRelation::getUserId,deleteUserIds);
                this.remove(queryWrapper);
            }
        }
        return true;
    }

    @Override
    public List<DOSProjectGroupUserRelationPo> getGroupMember(Integer projectGroupId) {
        List<DOSProjectGroupUserRelationPo> relationPos = new ArrayList<>();
        List<DOSProjectGroupUserRolePo> bindUsers = baseMapper.getBindUser(projectGroupId,"2", USER_ROLE_CODE);
        if (CollectionUtil.isNotEmpty(bindUsers)){
            // 如果列表第一的userType是1则说明为项目的管理者，此时需要将管理者剔除
            if (StrUtil.isNotBlank(bindUsers.get(0).getUserType()) && bindUsers.get(0).getUserType().equals("1")){
                assemblyPersonnelInfo(relationPos, bindUsers.subList(1,bindUsers.size()));
            }else {
                assemblyPersonnelInfo(relationPos, bindUsers);
            }
        }
        return relationPos;
    }

    @Override
    public List<DOSProjectGroupUserRelationPo> getGroupManager(Integer projectGroupId) {
        List<DOSProjectGroupUserRelationPo> relationPos = new ArrayList<>();
        List<DOSProjectGroupUserRolePo> bindUsers = baseMapper.getBindUser(projectGroupId, "1", MANAGER_ROLE_CODE);
        assemblyPersonnelInfo(relationPos, bindUsers);
        return relationPos;
    }

    @Override
    public List<DOSProjectGroupUserRelationPo> getProjectGroupUsers(Integer projectGroupId) {
        return baseMapper.getProjectGroupUsers(projectGroupId);
    }

    /**
     * @Author heyabo
     * @Description 获取查询结果
     * @Date 10:33 2022/9/7
     * @Param [relationPos, bindUsers]
     * @return void
     **/
    private void assemblyPersonnelInfo(List<DOSProjectGroupUserRelationPo> relationPos, List<DOSProjectGroupUserRolePo> bindUsers) {
        if (CollectionUtil.isNotEmpty(bindUsers)){
            Map<String, List<DOSProjectGroupUserRolePo>> userMaps = bindUsers.stream().collect(Collectors.groupingBy(DOSProjectGroupUserRolePo::getUserId));
            userMaps.forEach((key,value) ->{
                DOSProjectGroupUserRelationPo relationPo = BeanUtil.copyProperties(value.get(0), DOSProjectGroupUserRelationPo.class);
                relationPo.setUserRoles(value);
                relationPos.add(relationPo);

            });
            // 排序
            for (int i = 0; i < relationPos.size()-1;i++ ){
                for(int j =0; j < relationPos.size()-1-i;j++){
                    //取出对象
                    DOSProjectGroupUserRelationPo relationPo1 = relationPos.get(j);
                    DOSProjectGroupUserRelationPo relationPo2 = relationPos.get(j + 1);
                    int num1 = Integer.parseInt(StrUtil.isNotBlank(relationPo1.getUserType()) ? relationPo1.getUserType() : "0");
                    int num2 = Integer.parseInt(StrUtil.isNotBlank(relationPo2.getUserType()) ? relationPo2.getUserType() : "0");
                    if(num1 < num2){
                        relationPos.set(j,relationPo2);
                        relationPos.set(j+1,relationPo1);
                    }
                }
            }
        }
    }

    /**
     * @Author heyabo
     * @Description 校验为项目组分配的管理者是否合法
     * @Date 17:22 2022/9/7
     * @Param [relation]
     * @return void
     **/
    private void checkProjectGroupManager(DOSProjectGroupUserRelationVo relation) {
        if (relation.getUserType().equals("1")){
            Assert.isTrue(relation.getUserIds().size() == 1,"项目组管理者只能一个人");
            List<DOSRolePo> roles = dosRoleUserRelationService.getRoles(relation.getUserIds());
            List<String> roleCodes = roles.stream().map(DOSRolePo::getRoleCode).collect(Collectors.toList());
            Assert.isTrue(roleCodes.contains(DOSRoleEnum.TECHNOLOGY_MANAGER.getRoleCode())
                    || roleCodes.contains(DOSRoleEnum.QA_ADMINISTRATOR.getRoleCode())
                    || roleCodes.contains(DOSRoleEnum.ADMINISTRATOR.getRoleCode())
                    || roleCodes.contains(DOSRoleEnum.SUPER_ADMINISTRATOR.getRoleCode())
                    || roleCodes.contains(DOSRoleEnum.WEB_MANAGER.getRoleCode()),"请选择技术经理及以上进行绑定");
            // 根据项目组id和人员id查询该技术经理是否是项目组的成员
            LambdaQueryWrapper<DOSProjectGroupUserRelation> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(DOSProjectGroupUserRelation::getUserId, relation.getUserType())
                    .eq(DOSProjectGroupUserRelation::getProjectGroupId, relation.getProjectGroupId());
            this.remove(queryWrapper);
        }
    }
}
